package zero.tech.core.work;

import java.util.Date;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public abstract class DelayQueueWork implements Work, Delayed {
	public abstract DelayWorkQueue getDelayQueue();

	public abstract void delayrun();

	public DelayQueueWork(Object ext, long delaytime,boolean aync) {
		super();
		long now=System.currentTimeMillis();
		this.ext = ext;
		this.delaytime =delaytime;
		this.pushtime =now;
		this.runtime=now+delaytime;
		this.aync=aync;
	}
	
	public DelayQueueWork(Object ext, long delaytime) {
		super();
		long now=System.currentTimeMillis();
		this.ext = ext;
		this.delaytime =delaytime;
		this.pushtime =now;
		this.runtime=now+delaytime;
		this.aync=true;
	}

	@Override
	public void init(Object... objs) throws Exception {
		long now=System.currentTimeMillis();
		this.ext = (String) objs[0];
		this.delaytime = (long) objs[1];
		this.aync=(boolean) objs[2];
		this.pushtime =now;
		this.runtime=now+this.delaytime;
	}

	@Override
	public void run() {
		System.out.println(
				"提交时间:" + new Date(this.getPushtime()) + ",当前执行时间:" + new Date() + ",持续时间:" + this.getDelaytime());
		if(aync) {
			WorkManager.getManager().submit(new AynWork() {
				
				@Override
				public void run() {
					delayrun();
				}
				
				@Override
				public void init(Object... objs) throws Exception {
				}
			});
		}else {
			delayrun();
		}
	}

	/**
	 * 扩展属性
	 */
	protected Object ext;
	/**
	 * 过期时间
	 */
	protected long delaytime;
	/**
	 * 运行时刻
	 */
	protected long runtime;
	/**
	 * 提交时间
	 */
	protected long pushtime;
	/**
	 * 触发机制(true异步触发  false同步触发可能会因为业务耗时导致延迟队列后面的业务不能及时响应,推荐异步触发true)
	 */
	protected boolean aync;

	@Override
	public int compareTo(Delayed o) {
		DelayQueueWork delayWork = (DelayQueueWork) o;
		long runtime = delayWork.getRuntime();
		long runtime1 = this.getRuntime();
		return runtime == runtime1 ? 0 : runtime < runtime1 ? 1 : -1;
	}

	@Override
	public long getDelay(TimeUnit unit) {
		return unit.convert(this.delaytime + this.pushtime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
	}

	public Object getExt() {
		return ext;
	}

	public void setExt(Object ext) {
		this.ext = ext;
	}

	public long getDelaytime() {
		return delaytime;
	}

	public void setDelaytime(long delaytime) {
		this.delaytime = delaytime;
	}

	public long getPushtime() {
		return pushtime;
	}

	public void setPushtime(long pushtime) {
		this.pushtime = pushtime;
	}

	public long getRuntime() {
		return runtime;
	}

	public void setRuntime(long runtime) {
		this.runtime = runtime;
	}

	public boolean isAync() {
		return aync;
	}

	public void setAync(boolean aync) {
		this.aync = aync;
	}
}
